package com.jari.lg.service.analysis.epolice;

import com.jari.lg.domain.*;
import com.jari.lg.mapper.*;
import com.jari.lg.utils.BaseData;
import com.jari.lg.utils.LogUtil;
import com.jari.lg.utils.Utils;
import lombok.extern.slf4j.Slf4j;
import org.javatuples.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.jari.lg.utils.Utils.hourFormatterWithoutSep;

/**
 * @author ctl
 * @Description
 * @create 2022-03-22 10:19
 */
@Service
@Slf4j
public class EPoliceService {

    @Resource
    private ViolationDetailTaskResultMapper violationDetailTaskResultMapper;
    @Resource
    private ViolationHisMapper violationHisMapper;
    @Resource
    private ViolationTopLocationTaskResultMapper violationTopLocationTaskResultMapper;
    @Resource
    private ViolationJudgeDayMapper violationJudgeDayMapper;
    @Resource
    private ViolationJudgeMonthMapper violationJudgeMonthMapper;
    @Resource
    private ViolationJudgeYearMapper violationJudgeYearMapper;
    @Resource
    private ViolationTopLocationDayMapper violationTopLocationDayMapper;
    @Resource
    private ViolationTopLocationMonthMapper violationTopLocationMonthMapper;
    @Resource
    private ViolationTopLocationYearMapper violationTopLocationYearMapper;

    /**
     * 电警时空分析-抓拍统计
     */
    @Scheduled(cron = "0 0 * * * ? ")
    public void createViolationDetailTaskResult() {

        try {
            String jobInstanceId = hourFormatterWithoutSep.format(new Date());

            List<ViolationDetailTaskResult> resultList = new ArrayList();
            ViolationDetailTaskResult result = new ViolationDetailTaskResult();
            for (int i = 0; i < 50; i++) {

                DevBase ePolice = BaseData.ePoliceList.get(new Random().nextInt(BaseData.ePoliceList.size()));
                String ePoliceName = ePolice.getDevicename();
                String ePoliceCode = ePolice.getDevicecode();
                String plateNumber = Utils.createPlateNumber();
                String plateType = Utils.createPlateType();
                String carType = Utils.createCarType();
                String violationType = Utils.createViolationType();
                CrossBase crossBase = Utils.createJncByJncCode(ePolice.getCrosscode());

                result.setJobinstanceid(jobInstanceId);
                result.setEpolicename(ePoliceName);
                result.setEpolicecode(ePoliceCode);
                result.setPlatenumber(plateNumber);
                result.setPlatetype(plateType);
                result.setCartype(carType);
                result.setViolationtype(violationType);
                result.setKeyareaid(null);
                result.setJnccode(crossBase.getCrosscode());
                result.setJncname(crossBase.getCrossname());
                result.setRoadid(null);
                result.setRoadname(null);
                result.setDatetime(new Date());
                result.setKeyareaname(null);
                resultList.add(result);
                result = new ViolationDetailTaskResult();
            }
            violationDetailTaskResultMapper.insertBatch(resultList);
        } catch (Exception exception) {
            log.error(LogUtil.getStackMsg(exception));
        }
    }

    /**
     * 电警时空分析-实时违法抓拍
     */
    @Scheduled(cron = "0 0/10 * * * ? ")
    public void createViolationHis() {
        createViolationHisFromDate(new Date());
    }


    /**
     * 根据传入的时间生成违法历史数据
     *
     * @param date
     */
    public void createViolationHisFromDate(Date date) {
        try {
            List<ViolationHis> resultList = new ArrayList();
            ViolationHis result = new ViolationHis();
            for (int i = 0; i < 50; i++) {

                DevBase ePolice = BaseData.ePoliceList.get(new Random().nextInt(BaseData.ePoliceList.size()));
                String ePoliceName = ePolice.getDevicename();
                String ePoliceCode = ePolice.getDevicecode();
                String plateNumber = Utils.createPlateNumber();
                String plateType = Utils.createPlateType();
                String carType = Utils.createCarType();
                String violationType = Utils.createViolationType();
                CrossBase crossBase = Utils.createJncByJncCode(ePolice.getCrosscode());
                KeyArea keyArea = Utils.getKeyareaById(ePolice.getKeyareacode());

                result.setId(Utils.getUUID());
                result.setEpolicename(ePoliceName);
                result.setEpolicecode(ePoliceCode);
                result.setPlatenumber(plateNumber);
                result.setPlatetype(plateType);
                result.setCartype(carType);
                result.setViolationtype(violationType);
                result.setKeyareaid(keyArea == null ? null : keyArea.getId().toString());
                result.setKeyareaname(keyArea == null ? null : keyArea.getAreaname());
                result.setJnccode(crossBase.getCrosscode());
                result.setJncname(crossBase.getCrossname());
                result.setRoadid(null);
                result.setRoadname(null);
                result.setGmtcreate(date);
                result.setDatastatus("1");

                resultList.add(result);
                result = new ViolationHis();
            }
            violationHisMapper.insertBatch(resultList);
        } catch (Exception exception) {
            log.error(LogUtil.getStackMsg(exception));
        }
    }

    /**
     * 按月生成违法历史数据
     */
    public void batchCreateViolationHisPerMonth(Integer year, Integer month) {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, month - 1);    //month内部是从0开始
        Integer maxDay = c.getActualMaximum(Calendar.DAY_OF_MONTH);
        //天
        for (int i = 0; i < maxDay; i++) {
            c.set(Calendar.DAY_OF_MONTH, i + 1);
            //小时
            for (int j = 0; j < 24; j++) {
                c.set(Calendar.HOUR_OF_DAY, j);
                //每10分钟
                for (int k = 0; k < 6; k++) {
                    c.set(Calendar.MINUTE, k * 10);
                    c.set(Calendar.SECOND, 0);
                    Date date = c.getTime();
                    createViolationHisFromDate(date);
                }
            }
        }
    }

    /**
     * 电警时空分析-抓拍高发地Top10
     */
    @Scheduled(cron = "0 0 * * * ? ")
    public void createViolationTopLocationTaskResult() {
        try {
            String jobInstanceId = hourFormatterWithoutSep.format(new Date());

            List<ViolationTopLocationTaskResult> resultList = new ArrayList();
            ViolationTopLocationTaskResult result = new ViolationTopLocationTaskResult();
            //保存10个不相同数字作为获取电警的下标
            Set<Integer> ePoliceIndex = new HashSet<>();
            do {
                ePoliceIndex.add(new Random().nextInt(BaseData.ePoliceList.size()));
            } while (ePoliceIndex.size() < 10);
            Iterator<Integer> it = ePoliceIndex.iterator();
            while (it.hasNext()) {
                DevBase ePolice = BaseData.ePoliceList.get(it.next());
                String ePoliceName = ePolice.getDevicename();
                String ePoliceCode = ePolice.getDevicecode();

                String typeStr = String.join(",", BaseData.violationType);
                List<Integer> categoryNumList = new ArrayList<>();
                for (int i = 0; i < BaseData.violationType.length; i++) {
                    categoryNumList.add(new Random().nextInt(300) + 1);
                }
                String numStr = categoryNumList.stream().map(x -> String.valueOf(x)).collect(Collectors.joining(","));
                Integer sum = categoryNumList.stream().reduce((x, y) -> x + y).get();
                result.setJobinstanceid(jobInstanceId);
                result.setEpolicename(ePoliceName);
                result.setEpolicecode(ePoliceCode);
                result.setSum(sum);
                result.setTypestr(typeStr);
                result.setNumstr(numStr);
                resultList.add(result);
                result = new ViolationTopLocationTaskResult();
            }
            violationTopLocationTaskResultMapper.insertBatch(resultList);
        } catch (Exception exception) {
            log.error(LogUtil.getStackMsg(exception));
        }
    }

    /**
     * 电警时空分析-预警研判天表
     */
    @Scheduled(cron = "0 0 0 * * ? ")
    public void createViolationJudgeDay() {
        createViolationJudgeDayFromDate(new Date());
    }

    /**
     * 按月生成预警研判天表
     */
    public void batchCreateViolationJudgeDayPerMonth(Integer year, Integer month) {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, month - 1);    //month内部是从0开始
        Integer maxDay = c.getActualMaximum(Calendar.DAY_OF_MONTH);
        //天
        for (int i = 0; i < maxDay; i++) {
            c.set(Calendar.DAY_OF_MONTH, i + 1);
            c.set(Calendar.HOUR_OF_DAY, 0);
            c.set(Calendar.MINUTE, 0);
            c.set(Calendar.SECOND, 0);
            Date date = c.getTime();
            createViolationJudgeDayFromDate(date);
        }
    }

    /**
     * 根据传入的时间生成违法研判一天24个时段的数据
     *
     * @param date
     */
    public void createViolationJudgeDayFromDate(Date date) {
        try {
            List<ViolationJudgeDay> resultList = new ArrayList();
            ViolationJudgeDay result = new ViolationJudgeDay();
            for (int i = 0; i < 24; i++) {
                Pair<Date, Date> pair = Utils.getPeriodDateByPeriodId(date, i);
                Date periodStart = pair.getValue0();
                Date periodEnd = pair.getValue1();

                String typeStr = String.join(",", BaseData.violationType);
                List<Integer> categoryNumList = new ArrayList<>();
                //夜里违法记录变少
                if (i < 7 || i > 20) {
                    for (int j = 0; j < BaseData.violationType.length; j++) {
                        categoryNumList.add(new Random().nextInt(10) + 1);
                    }
                } else {
                    for (int j = 0; j < BaseData.violationType.length; j++) {
                        categoryNumList.add(new Random().nextInt(300) + 1);
                    }
                }

                String numStr = categoryNumList.stream().map(x -> String.valueOf(x)).collect(Collectors.joining(","));
                Integer sum = categoryNumList.stream().reduce((x, y) -> x + y).get();

                result.setPeriodstart(periodStart);
                result.setPeriodend(periodEnd);
                result.setPeriodnum(sum);
                result.setTypestr(typeStr);
                result.setNumstr(numStr);
                result.setDatetime(date);

                resultList.add(result);
                result = new ViolationJudgeDay();
            }
            violationJudgeDayMapper.insertBatch(resultList);
        } catch (Exception exception) {
            log.error(LogUtil.getStackMsg(exception));
        }
    }

    /**
     * 电警时空分析-预警研判月表
     */
    @Scheduled(cron = "0 0 0 1 * *")
    public void createViolationJudgeMonth() {
        createViolationJudgeMonthFromDate(new Date());
    }

    /**
     * 根据传入的时间生成违法研判1个月所有天的数据
     */
    public void createViolationJudgeMonthFromDate(Date date) {
        try {
            List<ViolationJudgeMonth> resultList = new ArrayList();
            ViolationJudgeMonth result = new ViolationJudgeMonth();
            Calendar c = Calendar.getInstance();
            c.setTime(date);
            int dayNo = 1;
            for (; dayNo <= c.getActualMaximum(Calendar.DAY_OF_MONTH); dayNo++) {
                c.set(Calendar.DAY_OF_MONTH, dayNo);
                Date day = c.getTime();

                String typeStr = String.join(",", BaseData.violationType);
                List<Integer> categoryNumList = new ArrayList<>();

                for (int j = 0; j < BaseData.violationType.length; j++) {
                    categoryNumList.add(new Random().nextInt(6000) + 1);
                }

                String numStr = categoryNumList.stream().map(x -> String.valueOf(x)).collect(Collectors.joining(","));
                Integer sum = categoryNumList.stream().reduce((x, y) -> x + y).get();

                result.setDay(day);
                result.setNum(sum);
                result.setTypestr(typeStr);
                result.setNumstr(numStr);
                result.setDatetime(date);

                resultList.add(result);
                result = new ViolationJudgeMonth();
            }
            violationJudgeMonthMapper.insertBatch(resultList);
        } catch (Exception exception) {
            log.error(LogUtil.getStackMsg(exception));
        }
    }

    /**
     * 按月生成预警研判月表
     */
    public void batchCreateViolationJudgeMonthPerMonth(Integer year, Integer month) {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, month - 1);    //month内部是从0开始
        c.set(Calendar.DAY_OF_MONTH, 1);
        Date date = c.getTime();
        createViolationJudgeMonthFromDate(date);
    }

    /**
     * 电警时空分析-预警研判年表
     */
    @Scheduled(cron = "0 0 0 1 1 *")
    public void createViolationJudgeYear() {
        createViolationJudgeYearFromDate(new Date());
    }

    /**
     * 根据传入的时间生成违法研判一年所有月的数据
     */
    public void createViolationJudgeYearFromDate(Date date) {

        try {
            List<ViolationJudgeYear> resultList = new ArrayList();
            ViolationJudgeYear result = new ViolationJudgeYear();
            Calendar c = Calendar.getInstance();
            c.setTime(date);

            int monthNo = 1;
            for (; monthNo <= 12; monthNo++) {
                c.set(Calendar.MONTH, monthNo - 1);
                Date month = c.getTime();
                String typeStr = String.join(",", BaseData.violationType);
                List<Integer> categoryNumList = new ArrayList<>();

                for (int j = 0; j < BaseData.violationType.length; j++) {
                    categoryNumList.add(new Random().nextInt(36000) + 1);
                }

                String numStr = categoryNumList.stream().map(x -> String.valueOf(x)).collect(Collectors.joining(","));
                Integer sum = categoryNumList.stream().reduce((x, y) -> x + y).get();

                result.setMonth(month);
                result.setNum(sum);
                result.setTypestr(typeStr);
                result.setNumstr(numStr);
                result.setDatetime(date);

                resultList.add(result);
                result = new ViolationJudgeYear();
            }
            violationJudgeYearMapper.insertBatch(resultList);
        } catch (Exception exception) {
            log.error(LogUtil.getStackMsg(exception));
        }
    }

    /**
     * 按年生成预警研判年表
     */
    public void batchCreateViolationJudgeYearPerYear(Integer year) {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, 0);    //month内部是从0开始
        c.set(Calendar.DAY_OF_MONTH, 1);
        Date date = c.getTime();
        createViolationJudgeYearFromDate(date);
    }

    @Scheduled(cron = "0 0 0 * * ?")
    public void createViolationTopLocationDay() {
        createViolationTopLocationDayFromDate(new Date());
    }

    private void createViolationTopLocationDayFromDate(Date date) {
        try {
            List<ViolationTopLocationDay> resultList = new ArrayList();
            ViolationTopLocationDay result = new ViolationTopLocationDay();

            for (int i = 0; i < BaseData.ePoliceList.size(); i++) {

                DevBase ePolice = BaseData.ePoliceList.get(i);

                String typeStr = String.join(",", BaseData.violationType);
                List<Integer> categoryNumList = new ArrayList<>();
                for (int j = 0; j < BaseData.violationType.length; j++) {
                    categoryNumList.add(new Random().nextInt(100) + 1);
                }

                String numStr = categoryNumList.stream().map(x -> String.valueOf(x)).collect(Collectors.joining(","));
                Integer sum = categoryNumList.stream().reduce((x, y) -> x + y).get();

                result.setEpolicename(ePolice.getDevicename());
                result.setEpolicecode(ePolice.getDevicecode());
                result.setSum(sum);
                result.setTypestr(typeStr);
                result.setNumstr(numStr);
                result.setGmtcreate(date);
                result.setDate(date);
                resultList.add(result);
                result = new ViolationTopLocationDay();

            }
            violationTopLocationDayMapper.insertBatch(resultList);
        } catch (Exception exception) {
            log.error(LogUtil.getStackMsg(exception));
        }
    }

    public void batchCreateViolationTopLocationDayPerMonth(Integer year, Integer month) {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, month - 1);    //month内部是从0开始
        Integer maxDay = c.getActualMaximum(Calendar.DAY_OF_MONTH);
        //天
        for (int i = 0; i < maxDay; i++) {
            c.set(Calendar.DAY_OF_MONTH, i + 1);
            c.set(Calendar.HOUR_OF_DAY, 0);
            c.set(Calendar.MINUTE, 0);
            c.set(Calendar.SECOND, 0);
            Date date = c.getTime();
            createViolationTopLocationDayFromDate(date);
        }
    }

    @Scheduled(cron = "0 0 0 1 * ? ")
    public void createViolationTopLocationMonth() {
        createViolationTopLocationMonthFromDate(new Date());
    }

    private void createViolationTopLocationMonthFromDate(Date date) {
        try {
            List<ViolationTopLocationMonth> resultList = new ArrayList();
            ViolationTopLocationMonth result = new ViolationTopLocationMonth();

            for (int i = 0; i < BaseData.ePoliceList.size(); i++) {

                DevBase ePolice = BaseData.ePoliceList.get(i);

                String typeStr = String.join(",", BaseData.violationType);
                List<Integer> categoryNumList = new ArrayList<>();
                for (int j = 0; j < BaseData.violationType.length; j++) {
                    categoryNumList.add(new Random().nextInt(500) + 1500);
                }

                String numStr = categoryNumList.stream().map(x -> String.valueOf(x)).collect(Collectors.joining(","));
                Integer sum = categoryNumList.stream().reduce((x, y) -> x + y).get();

                result.setEpolicename(ePolice.getDevicename());
                result.setEpolicecode(ePolice.getDevicecode());
                result.setSum(sum);
                result.setTypestr(typeStr);
                result.setNumstr(numStr);
                result.setGmtcreate(date);
                result.setDate(date);
                resultList.add(result);
                result = new ViolationTopLocationMonth();

            }
            violationTopLocationMonthMapper.insertBatch(resultList);
        } catch (Exception exception) {
            log.error(LogUtil.getStackMsg(exception));
        }
    }

    public void batchCreateViolationTopLocationMonthPerMonth(Integer year, Integer month) {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, month - 1);    //month内部是从0开始
        c.set(Calendar.DAY_OF_MONTH, 1);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        Date date = c.getTime();
        createViolationTopLocationMonthFromDate(date);

    }

    @Scheduled(cron = "0 0 0 1 1 ?")
    public void createViolationTopLocationYear() {
        createViolationTopLocationYearFromDate(new Date());
    }

    private void createViolationTopLocationYearFromDate(Date date) {
        try {
            List<ViolationTopLocationYear> resultList = new ArrayList();
            ViolationTopLocationYear result = new ViolationTopLocationYear();

            for (int i = 0; i < BaseData.ePoliceList.size(); i++) {

                DevBase ePolice = BaseData.ePoliceList.get(i);

                String typeStr = String.join(",", BaseData.violationType);
                List<Integer> categoryNumList = new ArrayList<>();
                for (int j = 0; j < BaseData.violationType.length; j++) {
                    categoryNumList.add(new Random().nextInt(5000) + 15000);
                }

                String numStr = categoryNumList.stream().map(x -> String.valueOf(x)).collect(Collectors.joining(","));
                Integer sum = categoryNumList.stream().reduce((x, y) -> x + y).get();

                result.setEpolicename(ePolice.getDevicename());
                result.setEpolicecode(ePolice.getDevicecode());
                result.setSum(sum);
                result.setTypestr(typeStr);
                result.setNumstr(numStr);
                result.setGmtcreate(date);
                result.setDate(date);
                resultList.add(result);
                result = new ViolationTopLocationYear();

            }
            violationTopLocationYearMapper.insertBatch(resultList);
        } catch (Exception exception) {
            log.error(LogUtil.getStackMsg(exception));
        }
    }

    public void batchCreateViolationTopLocationYearPerYear(Integer year) {
        Calendar c = Calendar.getInstance();
        c.set(Calendar.YEAR, year);
        c.set(Calendar.MONTH, 0);    //month内部是从0开始
        c.set(Calendar.DAY_OF_MONTH, 1);
        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        Date date = c.getTime();
        createViolationTopLocationYearFromDate(date);

    }
}
